package com.ml4ai.backend.web.business.task;

import com.ml4ai.backend.domain.base.BusinessType;
import com.ml4ai.backend.domain.base.IntraCityDistributionStatus;
import com.ml4ai.backend.domain.base.ProcessStatus;
import com.ml4ai.backend.dto.*;
import com.ml4ai.backend.security.SecurityUtils;
import com.ml4ai.backend.services.IntraCityDistributionTaskService;
import com.ml4ai.backend.services.MapService;
import com.ml4ai.backend.services.TaskService;
import com.ml4ai.backend.services.UserService;
import com.ml4ai.backend.utils.Bean2Bean;
import com.ml4ai.backend.utils.RestUtil;
import com.ml4ai.backend.web.util.MapSpec;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.time.Clock;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Created by uesr on 2018/9/9.
 */
@Api("任务接口")
@RestController
@RequestMapping("/api/business/task")
public class TaskRest {

    @Autowired
    TaskService taskService;

    @Autowired
    UserService userService;

    @Autowired
    IntraCityDistributionTaskService intraCityDistributionTaskService;

    @Autowired
    MapService mapService;

    @ApiOperation(value = "待接任务", httpMethod = "POST")
    @RequestMapping(value = "/queryIntraCityDistributionTask", method = RequestMethod.POST)
    public Map<String, Object> queryNewTask(@RequestBody QueryOptions options) {
        Map<String, Object> queryResult = new LinkedHashMap<>();
        IntraCityDistributionTaskDTO query = new IntraCityDistributionTaskDTO();
        query.setStatus("1");
        query.setProcessStatus(ProcessStatus.WaitTake);
        query.setIntraCityDistributionStatus(IntraCityDistributionStatus.WAIT_TAKE);
        List<IntraCityDistributionTaskDTO> tasks = intraCityDistributionTaskService.query(query);
        Map<Long, PointDTO> points = new LinkedHashMap<>();
        tasks.forEach(task -> points.put(task.getId(), new PointDTO(task.getSourceX(), task.getSourceY())));

        queryResult.put("list", tasks.stream().map(task -> {
            task.setCommodityName("");
            return task;
        }).map(MapSpec::intraCityDistributionTask2map).collect(Collectors.toList()));
        return RestUtil.success(queryResult);
    }

    @ApiOperation(value = "我创建的任务", httpMethod = "POST")
    @RequestMapping(value = "/queryMyTask", method = RequestMethod.POST)
    public Map<String, Object> queryMyTask(@RequestBody IntraCityDistributionTaskDTO options) {
        UserDTO user = SecurityUtils.getCurrentUser();
        Map<String, Object> queryResult = new LinkedHashMap<>();
        TaskDTO query = new TaskDTO();
        query.setStarterId(user.getId());
        query.setStatus("1");
        List<TaskDTO> task = taskService.query(query);
        queryResult.put("list", task.stream().map(MapSpec::task2map).collect(Collectors.toList()));
        return RestUtil.success(queryResult);
    }

    @ApiOperation(value = "任务详情", httpMethod = "POST")
    @RequestMapping(value = "/getIntraCityDistribution", method = RequestMethod.POST)
    public Map<String, Object> intraCityDistribution(@RequestBody IntraCityDistributionTaskDTO task) {
        return RestUtil.success(Optional.of(intraCityDistributionTaskService.findById(task.getId())).map(MapSpec::intraCityDistributionTask2map).get());
    }

    @ApiOperation(value = "新建任务", httpMethod = "POST")
    @RequestMapping(value = "/createIntraCityDistribution", method = RequestMethod.POST)
    public Map<String, Object> newTask(@Valid @RequestBody IntraCityDistributionTaskDTO intraCityDistributionTaskDTO, BindingResult bindingResult) {
        Map<String, Object> data = new LinkedHashMap<>();
        if (bindingResult.hasErrors()) {
            return RestUtil.failure("缺少必要的参数", null);
        }
        IntraCityDistributionTaskDTO intraCityDistributionTask = new IntraCityDistributionTaskDTO();
        new Bean2Bean().copyProperties(intraCityDistributionTaskDTO, intraCityDistributionTask);

        String businessCode = taskService.genCode(BusinessType.IntraCityDistribution);
        intraCityDistributionTask.setBusinessCode(businessCode);

        intraCityDistributionTask.setProcessStatus(ProcessStatus.New);
        intraCityDistributionTask.setStatus("1");
        intraCityDistributionTask.setIntraCityDistributionStatus(IntraCityDistributionStatus.NEW);
        intraCityDistributionTask.setBusinessType(BusinessType.IntraCityDistribution);
        intraCityDistributionTask.setStartTime(Clock.systemUTC().millis());
        intraCityDistributionTask.setStarter(SecurityUtils.getCurrentUser());
        intraCityDistributionTask.setStarterId(SecurityUtils.getCurrentUser().getId());
        intraCityDistributionTask.setBusinessTitle(intraCityDistributionTask.getBusinessType().getName() + "-" + intraCityDistributionTask.getCommodityName());
        computeDistance(intraCityDistributionTask);
        intraCityDistributionTask.setLocationX(intraCityDistributionTask.getSourceX());
        intraCityDistributionTask.setLocationY(intraCityDistributionTask.getSourceY());
        intraCityDistributionTask = intraCityDistributionTaskService.save(intraCityDistributionTask);
        if (intraCityDistributionTask != null) {
            data.put("obj", intraCityDistributionTask);
            return RestUtil.success(data);
        } else {
            return RestUtil.failure();
        }
    }

    @ApiOperation(value = "更新任务", httpMethod = "POST")
    @RequestMapping(value = "/saveIntraCityDistribution", method = RequestMethod.POST)
    public Map<String, Object> saveIntraCityDistribution(@Valid @RequestBody IntraCityDistributionTaskDTO intraCityDistributionTaskDTO, BindingResult bindingResult) {
        Map<String, Object> data = new LinkedHashMap<>();
        if (bindingResult.hasErrors()) {
            return RestUtil.failure("缺少必要的参数", null);
        }
        IntraCityDistributionTaskDTO intraCityDistributionTask = intraCityDistributionTaskService.findById(intraCityDistributionTaskDTO.getId());
        switch (intraCityDistributionTask.getIntraCityDistributionStatus()) {
            case NEW:
            case CONFIRM:
                break;
            default:
                return RestUtil.failure("状态错误，该状态的订单不允许修改!");
        }
        new Bean2Bean().copyProperties(intraCityDistributionTaskDTO, intraCityDistributionTask);
        intraCityDistributionTask.setProcessStatus(ProcessStatus.New);
        intraCityDistributionTask.setStatus("1");
        intraCityDistributionTask.setIntraCityDistributionStatus(IntraCityDistributionStatus.NEW);
        intraCityDistributionTask.setBusinessTitle(intraCityDistributionTask.getBusinessType().getName() + "-" + intraCityDistributionTask.getCommodityName());
        intraCityDistributionTask.setBusinessType(BusinessType.IntraCityDistribution);
        intraCityDistributionTask.setStartTime(Clock.systemUTC().millis());
        intraCityDistributionTask.setStarter(SecurityUtils.getCurrentUser());
        intraCityDistributionTask.setStarterId(SecurityUtils.getCurrentUser().getId());
        computeDistance(intraCityDistributionTask);
        intraCityDistributionTask.setLocationX(intraCityDistributionTask.getSourceX());
        intraCityDistributionTask.setLocationY(intraCityDistributionTask.getSourceY());
        intraCityDistributionTask = intraCityDistributionTaskService.save(intraCityDistributionTask);
        if (intraCityDistributionTask != null) {
            data.put("obj", intraCityDistributionTask);
            return RestUtil.success(data);
        } else {
            return RestUtil.failure();
        }
    }

    private void computeDistance(IntraCityDistributionTaskDTO intraCityDistributionTask) {
        MapRouteMatrixDTO mapRouteMatrixDTO = new MapRouteMatrixDTO();
        mapRouteMatrixDTO.setOrigins(Arrays.asList(new MapAddressDTO(null, intraCityDistributionTask.getSourceX(), intraCityDistributionTask.getSourceY())));
        mapRouteMatrixDTO.setDestinations(Arrays.asList(new MapAddressDTO(null, intraCityDistributionTask.getDestinationX(), intraCityDistributionTask.getDestinationY())));
        mapRouteMatrixDTO.setOperator(MapRouteMatrixDTO.OperatorRiding);
        mapRouteMatrixDTO.setTactics(10);
        Map<String, Object> route = mapService.route(mapRouteMatrixDTO);
        if (route != null) {
            List<Map<String, Object>> result = (List) route.get("result");
            Map<String, Object> first = result.get(0);
            String distance = (String) first.get("distance");
            intraCityDistributionTask.setDistance(Double.valueOf(distance) / 1000D);
        }
    }


    @ApiOperation(value = "删除任务", httpMethod = "POST")
    @RequestMapping(value = "/deleteIntraCityDistribution", method = RequestMethod.POST)
    public Map<String, Object> deleteIntraCityDistribution(@RequestBody IntraCityDistributionTaskDTO intraCityDistributionTaskDTO) {
        boolean delete = intraCityDistributionTaskService.delete(intraCityDistributionTaskDTO.getId());
        if (delete) {
            return RestUtil.success("删除成功");
        } else {
            return RestUtil.failure();
        }
    }

    @ApiOperation(value = "发布任务", httpMethod = "POST")
    @RequestMapping(value = "/publishIntraCityDistribution", method = RequestMethod.POST)
    public Map<String, Object> publishTheIntraCityDistribution(@RequestBody IntraCityDistributionTaskDTO intraCityDistributionTaskDTO) {
        IntraCityDistributionTaskDTO intraCityDistributionTask = intraCityDistributionTaskService.findById(intraCityDistributionTaskDTO.getId());
        if (intraCityDistributionTask != null) {
            intraCityDistributionTask.setIntraCityDistributionStatus(IntraCityDistributionStatus.WAIT_TAKE);
            intraCityDistributionTask.setProcessStatus(ProcessStatus.WaitTake);
            intraCityDistributionTaskService.save(intraCityDistributionTask);
            return RestUtil.success("删除成功");
        } else {
            return RestUtil.failure("给定的id错误");
        }
    }

    @Data
    public static class QueryOptions {
        private Double locX;
        private Double locY;
    }
}
